home *** CD-ROM | disk | FTP | other *** search
/ TPUG - Toronto PET Users Group / TPUG Users Group CD / TPUG Users Group CD.iso / AMIGA / AMICUS / AMICUS02.ADF / Emacs / random.c < prev    next >
C/C++ Source or Header  |  1989-05-30  |  13KB  |  389 lines

  1. /* random.c */
  2.  
  3. /*
  4.  * This file contains the command processing functions for a number of random
  5.  * commands. There is no functional grouping here, for sure.
  6.  */
  7.  
  8. #include        <stdio.h>
  9. #include        "ed.h"
  10.  
  11. int     tabsize;                        /* Tab size (0: use real tabs)  */
  12.  
  13. /*
  14.  * Set fill column to n. 
  15.  */
  16. setfillcol(f, n)
  17. {
  18.         fillcol = n;
  19.         return(TRUE);
  20. }
  21.  
  22. /*
  23.  * Display the current position of the cursor, in origin 1 X-Y coordinates,
  24.  * the character that is under the cursor (in octal), and the fraction of the
  25.  * text that is before the cursor. The displayed column is not the current
  26.  * column, but the column that would be used on an infinite width display.
  27.  * Normally this is bound to "C-X =".
  28.  */
  29. showcpos(f, n)
  30. {
  31.         register LINE   *clp;
  32.         register long   nch;
  33.         register int    cbo;
  34.         register long   nbc;
  35.         register int    cac;
  36.         register int    ratio;
  37.         register int    col;
  38.         register int    i;
  39.         register int    c;
  40.  
  41.         clp = lforw(curbp->b_linep);            /* Grovel the data.     */
  42.         cbo = 0;
  43.         nch = 0;
  44.         for (;;) {
  45.                 if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
  46.                         nbc = nch;
  47.                         if (cbo == llength(clp))
  48.                                 cac = '\n';
  49.                         else
  50.                                 cac = lgetc(clp, cbo);
  51.                 }
  52.                 if (cbo == llength(clp)) {
  53.                         if (clp == curbp->b_linep)
  54.                                 break;
  55.                         clp = lforw(clp);
  56.                         cbo = 0;
  57.                 } else
  58.                         ++cbo;
  59.                 ++nch;
  60.         }
  61.         col = getccol(FALSE);                   /* Get real column.     */
  62.         ratio = 0;                              /* Ratio before dot.    */
  63.         if (nch != 0)
  64.                 ratio = (100L*nbc) / nch;
  65.         mlwrite("X=%d Y=%d CH=0x%x .=%D (%d%% of %D)",
  66.                 col+1, currow+1, cac, nbc, ratio, nch);
  67.         return (TRUE);
  68. }
  69.  
  70. /*
  71.  * Return current column.  Stop at first non-blank given TRUE argument.
  72.  */
  73. getccol(bflg)
  74. int bflg;
  75. {
  76.         register int c, i, col;
  77.         col = 0;
  78.         for (i=0; i<curwp->w_doto; ++i) {
  79.                 c = lgetc(curwp->w_dotp, i);
  80.                 if (c!=' ' && c!='\t' && bflg)
  81.                         break;
  82.                 if (c == '\t')
  83.                         col |= 0x07;
  84.                 else if (c<0x20 || c==0x7F)
  85.                         ++col;
  86.                 ++col;
  87.         }
  88.         return(col);
  89. }
  90.  
  91. /*
  92.  * Twiddle the two characters on either side of dot. If dot is at the end of
  93.  * the line twiddle the two characters before it. Return with an error if dot
  94.  * is at the beginning of line; it seems to be a bit pointless to make this
  95.  * work. This fixes up a very common typo with a single stroke. Normally bound
  96.  * to "C-T". This always works within a line, so "WFEDIT" is good enough.
  97.  */
  98. twiddle(f, n)
  99. {
  100.         register LINE   *dotp;
  101.         register int    doto;
  102.         register int    cl;
  103.         register int    cr;
  104.  
  105.         dotp = curwp->w_dotp;
  106.         doto = curwp->w_doto;
  107.         if (doto==llength(dotp) && --doto<0)
  108.                 return (FALSE);
  109.         cr = lgetc(dotp, doto);
  110.         if (--doto < 0)
  111.                 return (FALSE);
  112.         cl = lgetc(dotp, doto);
  113.         lputc(dotp, doto+0, cr);
  114.         lputc(dotp, doto+1, cl);
  115.         lchange(WFEDIT);
  116.         return (TRUE);
  117. }
  118.  
  119. /*
  120.  * Quote the next character, and insert it into the buffer. All the characters
  121.  * are taken literally, with the exception of the newline, which always has
  122.  * its line splitting meaning. The character is always read, even if it is
  123.  * inserted 0 times, for regularity. Bound to "M-Q" (for me) and "C-Q" (for
  124.  * Rich, and only on terminals that don't need XON-XOFF).
  125.  */
  126. quote(f, n)
  127. {
  128.         register int    s;
  129.         register int    c;
  130.  
  131.         c = (*term.t_getchar)();
  132.         if (n < 0)
  133.                 return (FALSE);
  134.         if (n == 0)
  135.                 return (TRUE);
  136.         if (c == '\n') {
  137.                 do {
  138.                         s = lnewline();
  139.                 } while (s==TRUE && --n);
  140.                 return (s);
  141.         }
  142.         return (linsert(n, c));
  143. }
  144.  
  145. /*
  146.  * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  147.  * tab into file.  If given argument, n, of zero, change to true tabs.
  148.  * If n > 1, simulate tab stop every n-characters using spaces. This has to be
  149.  * done in this slightly funny way because the tab (in ASCII) has been turned
  150.  * into "C-I" (in 10 bit code) already. Bound to "C-I".
  151.  */
  152. tab(f, n)
  153. {
  154.         if (n < 0)
  155.                 return (FALSE);
  156.         if (n == 0 || n > 1) {
  157.                 tabsize = n;
  158.                 return(TRUE);
  159.         }
  160.         if (! tabsize)
  161.                 return(linsert(1, '\t'));
  162.         return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
  163. }
  164.  
  165. /*
  166.  * Open up some blank space. The basic plan is to insert a bunch of newlines,
  167.  * and then back up over them. Everything is done by the subcommand
  168.  * procerssors. They even handle the looping. Normally this is bound to "C-O".
  169.  */
  170. openline(f, n)
  171. {
  172.         register int    i;
  173.         register int    s;
  174.  
  175.         if (n < 0)
  176.                 return (FALSE);
  177.         if (n == 0)
  178.                 return (TRUE);
  179.         i = n;                                  /* Insert newlines.     */
  180.         do {
  181.                 s = lnewline();
  182.         } while (s==TRUE && --i);
  183.         if (s == TRUE)                          /* Then back up overtop */
  184.                 s = backchar(f, n);             /* of them all.         */
  185.         return (s);
  186. }
  187.  
  188. /*
  189.  * Insert a newline. Bound to "C-M". If you are at the end of the line and the
  190.  * next line is a blank line, just move into the blank line. This makes "C-O"
  191.  * and "C-X C-O" work nicely, and reduces the ammount of screen update that
  192.  * has to be done. This would not be as critical if screen update were a lot
  193.  * more efficient.
  194.  */
  195. newline(f, n)
  196. {
  197.         int nicol;
  198.         register LINE   *lp;
  199.         register int    s;
  200.  
  201.         if (n < 0)
  202.                 return (FALSE);
  203.         while (n--) {
  204.                 lp = curwp->w_dotp;
  205.                 if (llength(lp) == curwp->w_doto
  206.                 && lp != curbp->b_linep
  207.                 && llength(lforw(lp)) == 0) {
  208.                         if ((s=forwchar(FALSE, 1)) != TRUE)
  209.                                 return (s);
  210.                 } else if ((s=lnewline()) != TRUE)
  211.                         return (s);
  212.         }
  213.         return (TRUE);
  214. }
  215.  
  216. /*
  217.  * Delete blank lines around dot. What this command does depends if dot is
  218.  * sitting on a blank line. If dot is sitting on a blank line, this command
  219.  * deletes all the blank lines above and below the current line. If it is
  220.  * sitting on a non blank line then it deletes all of the blank lines after
  221.  * the line. Normally this command is bound to "C-X C-O". Any argument is
  222.  * ignored.
  223.  */
  224. deblank(f, n)
  225. {
  226.         register LINE   *lp1;
  227.         register LINE   *lp2;
  228.         register int    nld;
  229.  
  230.         lp1 = curwp->w_dotp;
  231.         while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  232.                 lp1 = lp2;
  233.         lp2 = lp1;
  234.         nld = 0;
  235.         while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  236.                 ++nld;
  237.         if (nld == 0)
  238.                 return (TRUE);
  239.         curwp->w_dotp = lforw(lp1);
  240.         curwp->w_doto = 0;
  241.         return (ldelete(nld));
  242. }
  243.  
  244. /*
  245.  * Insert a newline, then enough tabs and spaces to duplicate the indentation
  246.  * of the previous line. Assumes tabs are every eight characters. Quite simple.
  247.  * Figure out the indentation of the current line. Insert a newline by calling
  248.  * the standard routine. Insert the indentation by inserting the right number
  249.  * of tabs and spaces. Return TRUE if all ok. Return FALSE if one of the
  250.  * subcomands failed. Normally bound to "C-J".
  251.  */
  252. indent(f, n)
  253. {
  254.         register int    nicol;
  255.         register int    c;
  256.         register int    i;
  257.  
  258.         if (n < 0)
  259.                 return (FALSE);
  260.         while (n--) {
  261.                 nicol = 0;
  262.                 for (i=0; i<llength(curwp->w_dotp); ++i) {
  263.                         c = lgetc(curwp->w_dotp, i);
  264.                         if (c!=' ' && c!='\t')
  265.                                 break;
  266.                         if (c == '\t')
  267.                                 nicol |= 0x07;
  268.                         ++nicol;
  269.                 }
  270.                 if (lnewline() == FALSE
  271.                 || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
  272.                 || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
  273.                         return (FALSE);
  274.         }
  275.         return (TRUE);
  276. }
  277.  
  278. /*
  279.  * Delete forward. This is real easy, because the basic delete routine does
  280.  * all of the work. Watches for negative arguments, and does the right thing.
  281.  * If any argument is present, it kills rather than deletes, to prevent loss
  282.  * of text if typed with a big argument. Normally bound to "C-D".
  283.  */
  284. forwdel(f, n)
  285. {
  286.         if (n < 0)
  287.                 return (backdel(f, -n));
  288.         if (f != FALSE) {                       /* Really a kill.       */
  289.                 if ((lastflag&CFKILL) == 0)
  290.                         kdelete();
  291.                 thisflag |= CFKILL;
  292.         }
  293.         return (ldelete(n, f));
  294. }
  295.  
  296. /*
  297.  * Delete backwards. This is quite easy too, because it's all done with other
  298.  * functions. Just move the cursor back, and delete forwards. Like delete
  299.  * forward, this actually does a kill if presented with an argument. Bound to
  300.  * both "RUBOUT" and "C-H".
  301.  */
  302. backdel(f, n)
  303. {
  304.         register int    s;
  305.  
  306.         if (n < 0)
  307.                 return (forwdel(f, -n));
  308.         if (f != FALSE) {                       /* Really a kill.       */
  309.                 if ((lastflag&CFKILL) == 0)
  310.                         kdelete();
  311.                 thisflag |= CFKILL;
  312.         }
  313.         if ((s=backchar(f, n)) == TRUE)
  314.                 s = ldelete(n, f);
  315.         return (s);
  316. }
  317.  
  318. /*
  319.  * Kill text. If called without an argument, it kills from dot to the end of
  320.  * the line, unless it is at the end of the line, when it kills the newline.
  321.  * If called with an argument of 0, it kills from the start of the line to dot.
  322.  * If called with a positive argument, it kills from dot forward over that
  323.  * number of newlines. If called with a negative argument it kills backwards
  324.  * that number of newlines. Normally bound to "C-K".
  325.  */
  326. kill(f, n)
  327. {
  328.         register int    chunk;
  329.         register LINE   *nextp;
  330.  
  331.         if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
  332.                 kdelete();                      /* last wasn't a kill.  */
  333.         thisflag |= CFKILL;
  334.         if (f == FALSE) {
  335.                 chunk = llength(curwp->w_dotp)-curwp->w_doto;
  336.                 if (chunk == 0)
  337.                         chunk = 1;
  338.         } else if (n == 0) {
  339.                 chunk = curwp->w_doto;
  340.                 curwp->w_doto = 0;
  341.         } else if (n > 0) {
  342.                 chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  343.                 nextp = lforw(curwp->w_dotp);
  344.                 while (--n) {
  345.                         if (nextp == curbp->b_linep)
  346.                                 return (FALSE);
  347.                         chunk += llength(nextp)+1;
  348.                         nextp = lforw(nextp);
  349.                 }
  350.         } else {
  351.                 mlwrite("neg kill");
  352.                 return (FALSE);
  353.         }
  354.         return (ldelete(chunk, TRUE));
  355. }
  356.  
  357. /*
  358.  * Yank text back from the kill buffer. This is really easy. All of the work
  359.  * is done by the standard insert routines. All you do is run the loop, and
  360.  * check for errors. Bound to "C-Y". The blank lines are inserted with a call
  361.  * to "newline" instead of a call to "lnewline" so that the magic stuff that
  362.  * happens when you type a carriage return also happens when a carriage return
  363.  * is yanked back from the kill buffer.
  364.  */
  365. yank(f, n)
  366. {
  367.         register int    c;
  368.         register int    i;
  369.         extern   int    kused;
  370.  
  371.         if (n < 0)
  372.                 return (FALSE);
  373.         while (n--) {
  374.                 i = 0;
  375.                 while ((c=kremove(i)) >= 0) {
  376.                         if (c == '\n') {
  377.                                 if (newline(FALSE, 1) == FALSE)
  378.                                         return (FALSE);
  379.                         } else {
  380.                                 if (linsert(1, c) == FALSE)
  381.                                         return (FALSE);
  382.                         }
  383.                         ++i;
  384.                 }
  385.         }
  386.         return (TRUE);
  387. }
  388.  
  389.